﻿package State 
{
	import Box2DAS.Common.V2;
	import Box2DAS.Dynamics.ContactEvent;
	import com.citrusengine.core.CitrusEngine;
	import com.citrusengine.core.CitrusObject;
	import com.citrusengine.core.State;
	import com.citrusengine.objects.CitrusSprite;
	import com.citrusengine.objects.platformer.Baddy;
	import com.citrusengine.objects.platformer.Hero;
	import com.citrusengine.objects.platformer.MovingPlatform;
	import com.citrusengine.objects.platformer.Platform;
	import com.citrusengine.objects.platformer.Sensor;
	import com.citrusengine.physics.Box2D;
	import com.citrusengine.math.MathVector;
	import com.citrusengine.physics.simple.CitrusSolver;
	import com.citrusengine.view.spriteview.SpriteArt;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.setTimeout;
	import org.osflash.signals.Signal;
	
	/**
	 * ...
	 * @author ...
	 */
	
	public class GameState extends State
	{
		[Embed(source="../../bin/main_ui.swf", symbol="base_ui")]
		public var main_ui:Class;
		private var ui:Sprite;
		
		private var _score:Number;
		public function get score():Number { return _score; }
		public function set score(n:Number):void { _score = n; }
		
		private var elapsedSpawnTime:Number;
		
		private var leftWall:Platform;
		private var rightWall:Platform;
		private var ground:Platform;
		
		private var sprBackground:CitrusSprite;
		private var sprBackgroundController:SpriteArt;
		private var bgScrollSpeed:int;
		
		private var _hero:Bird;
		public function get hero():Bird { return _hero; }
		
		private var heroHitSensor:Sensor;
		
		private var _level:int;
		private var isPlaying:Boolean;
		
		private var _minSecondSpawn:Array = [1.5, 1.2, 1.0, 0.8];
		public var _currSpawn:Number;
		
		private var _enemyKills:int;
		public function get enemyKills():int { return _enemyKills; }
		public function set enemyKills(i:int):void { _enemyKills += i; }
		
		private var apakan:CitrusSprite;
		private var leftPillar:CitrusSprite;
		private var rightPillar:CitrusSprite;
		
		private var totalDrop:int;
		
		public function GameState(level:int ) 
		{
			super();
			
			_score = 0;
			_enemyKills = 0;
			elapsedSpawnTime = 0;
			isPlaying = true;
			
			_level = level;
			
			var i:int = _level - 1;
			_currSpawn = _minSecondSpawn[i] + Math.random();
			
			trace("LEVEL: " + level);
			this.alpha = 0;
			addEventListener(Event.ENTER_FRAME, fadeIn);
		}
		
		public function fadeIn(e:Event):void
		{
			this.alpha += 0.05;
			if (alpha >= 1)
			{
				removeEventListener(Event.ENTER_FRAME, fadeIn);
			}
		}
		
		public function switchBackground(theme:int):void
		{
			switch(theme)
			{
				case GameBalance.THEME_FOREST: sprBackground = new CitrusSprite("BG2", { view: "bg_forest.swf" } ); break;
				case GameBalance.THEME_SKY: sprBackground = new CitrusSprite("BG3", { view: "bg_sky.swf" } ); break;
				
				case GameBalance.THEME_SPACE: sprBackground = new CitrusSprite("BG4", { view: "bg_stars.swf" } ); break;
				case GameBalance.THEME_UNDERGROUND: sprBackground = new CitrusSprite("BG1", { view: "bg_underground.swf" } ); break;
			}
		}
		private function backgroundLoaded(e:Event = null):void
		{
			//backgroundGraphic.content.alpha = 0.5;
		}
		
		override public function initialize():void 
		{
			super.initialize();
			
			var box2D:Box2D = new Box2D("NAME"); // use any name you want for "NAME"
			add(box2D);
			
			//box2D.visible = true; // sets the debug drawing visible. Allows collision areas to be seen. TURN THIS OFF WHEN RELEASING THE GAME
			
			sprBackground = new CitrusSprite("BG1", { view: "bg_underground.swf" } );
			add(sprBackground);
			sprBackgroundController = this.view.getArt(sprBackground) as SpriteArt;
			sprBackgroundController.loader.contentLoaderInfo.addEventListener(Event.COMPLETE, backgroundLoaded);
			
			
			//background.view.alpha = 0;
			
			apakan = new CitrusSprite("Apakan", { view: "base.swf" } );
			add(apakan);
			apakan.x = 0;
			apakan.y = 150;
			apakan.parallax = 0;
			
			leftPillar = new CitrusSprite("LeftPillar", { view: "pillar.swf" } ); // FIX THE INVISIBLE PADER
			add(leftPillar);
			leftPillar.x = -50;
			leftPillar.y = -100;
			leftPillar.parallax = 0;
			
			rightPillar = new CitrusSprite("RightPillar", { view: "pillar.swf" } );
			add(rightPillar);
			rightPillar.x = 750;
			rightPillar.y = -100;
			rightPillar.parallax = 0;
			
			_hero = new Bird("RAVEN", { view:"Raven.swf", height: 120});
			add(_hero);
			_hero.x = 320;
			_hero.y = 0;
			_hero.offsetY = 10; //uurong yung bounding box
			_hero.toggle_invi.add(changeHeroAlpha);
			
			
			leftWall = new Platform("LEFT WALL", { width: 100, height: 50000 } ); // width and height are required to be set initially because Box2D does not cope up with midway changes to object dimensions
			add(leftWall);
			leftWall.x = 0;
			leftWall.y = 400;
			
			rightWall = new Platform("RIGHT WALL", { width: 100, height: 50000 } ); // width and height are required to be set initially because Box2D does not cope up with midway changes to object dimensions
			add(rightWall);
			rightWall.x = 800;
			rightWall.y = 400;
			
			ground = new Platform("GROUND", { width: 1000, height: 250 } ); //trigger when character passes here
			add(ground);
			ground.x = 300;
			ground.y = 180;
			bgScrollSpeed = 1 + (0.2 * PlayerUpgrades.lvlElevatorSpeed);
			
			if (ground)
			{
				view.cameraTarget = ground;
				view.cameraOffset = new MathVector(stage.stageWidth / 2, stage.stageHeight / 1);
				view.cameraEasing = new MathVector(0, 0.4);
			}
			
			ui = new main_ui();
			addChild(ui);
			ui.y = 455;
			
		}
		
		private function changeHeroAlpha():void
		{
			var heroGraphic:SpriteArt = view.getArt(_hero) as SpriteArt;
			
			if(heroGraphic.content.alpha == 1)
				heroGraphic.content.alpha = 0.3;
			else 
				heroGraphic.content.alpha = 1;
		}
		
		public override function update(timeDelta:Number):void
		{
			//Call update on all objects
			var garbage:Array = [];
			var n:Number = _objects.length;
			for (var i:int = 0; i < n; i++)
			{
				var object:CitrusObject = _objects[i];
				if (object.kill)
					garbage.push(object);
				else
					object.update(timeDelta);
			}
			
			//Destroy all objects marked for destroy
			//TODO There might be a limit on the number of Box2D bodies that you can destroy in one tick?
			n = garbage.length;
			for (i = 0; i < n; i++)
			{
				var garbageObject:CitrusObject = garbage[i];
				if (garbageObject.name == "BAD")
					_enemyKills += 1;
				_objects.splice(_objects.indexOf(garbageObject), 1);
				garbageObject.destroy();
				_view.removeArt(garbageObject);
				
				
			}
			
			//Update the input object
			_input.update();
			
			//Update the state's view
			_view.update();
			
			if (isPlaying)
			{
				updateScore();
				updateEnemySpawn(timeDelta);
				//check losing condition
				checkLosingCondition();
			}
			
		}
		
		private function checkLosingCondition():void
		{
			//trace("BADDIES COUNT" + getObjectsByType(Baddy).length);
			if (getObjectsByType(Baddy).length >= 8 || _hero.life <= 0)
			{
				_hero.controlsEnabled = false;
				gameOver();
			}
		}
		
		private function gameOver():void
		{
			//trace("FINAL SCORE: " + score);
			isPlaying = false;
			//nextLevelTrigger.destroy();
			bgScrollSpeed = 0;
			if (getObjectsByType(Baddy).length >= 8)
			{
				addEventListener(Event.ENTER_FRAME, dropElevator);
				view.cameraEasing = new MathVector(0, 0);
			}
			
			
			setTimeout(displayBonusWindow, 1200);
		}
		
		private function dropElevator(e:Event):void 
		{
			
			totalDrop += 30;
			leftPillar.y += 30;
			rightPillar.y += 30;
			apakan.y += 30;
			ground.y += 30;
			
			if (totalDrop >= 1500)
				removeEventListener(Event.ENTER_FRAME, dropElevator);
		}
		
		private function displayBonusWindow():void
		{
			var floorCoins:int = score / 100;
			
			var killCoins:int = _enemyKills;
			var u:State.UpgradeState = new State.UpgradeState(floorCoins, killCoins);
			addChild(u);
			u.x = 207;
			u.y = 43;
		}
		
		private function updateScore():void
		{
			_score += (1 + PlayerUpgrades.lvlElevatorSpeed * 0.2);
			
			//trace("SCORE: " + _score);
			
			var floor:int = _score / 100;
			ui["floorField"].text = "" + floor;
			ui["lifeField"].text = "" + hero.life;
		}
		
		private function updateEnemySpawn(a:Number):void
		{
			elapsedSpawnTime += a;
			if (isPlaying && elapsedSpawnTime >= _currSpawn)
			{
				spawnEnemy();
				elapsedSpawnTime = 0;
				var i:int = _level - 1;
				_currSpawn = _minSecondSpawn[i] + Math.random();
			}
			
		}
		
		private function spawnEnemy():void 
		{
			var b:Baddy = new Baddy("BAD", {width: 50, height: 45, view:"Pudding.swf"} );
			add(b);
			//b.x = 390;
			b.x = Math.random() * 420 + 130;
			b.y = ground.y - 850;
			b.offsetY = -5; //uurong yung bounding box
			b.gravity = 0.4;
			
		}
		
		
		public function setElevatorSpeed(n:Number):void
		{
			bgScrollSpeed = n;
			trace("CHEAT ENABLED. Ground speed = " + n);
		}
		
		private function loadNextLevel():void
		{
			addEventListener(Event.ENTER_FRAME, fadeOut);
		}
		
		private function fadeOut(e:Event):void
		{
			this.alpha -= 0.06;
			if (this.alpha <= 0)
			{
				removeEventListener(Event.ENTER_FRAME, fadeOut);
				var nextLevel:int = _level + 1;
				trace("LEVEL UP TO LEVEL " + nextLevel);
				//CitrusEngine.getInstance().state = new State.GameState(nextLevel, score, hero.life);
				
				//TODO: Switch background into something else
			}
		}
		
	}
	
}